﻿#region License, Terms and Conditions
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;

namespace raya.Library
{
    public class Img
    {
#if AZURE
        public const string blobImageContainerName = "photos";
#endif
        // supported image types
        public static readonly List<string> acceptedTypes = new List<string> { "jpg" };
                        
        public enum size
        {
            thumb,
            small,
            normal
        }

        public static Pair getImageDimensionsFromSize(size size)
        {
            switch (size)
            {
                case size.thumb:
                    return new Pair(50, 50);
                case size.small:
                    return new Pair(64, 64);
                case size.normal:
                    return new Pair(129, 151);
                default:
                    throw new ArgumentException();
            }
        }
        public static string by_size(string filePath, int width, int height)
        {
            return by_size(filePath, width, height, false);
        }

        public static string by_size(string filePath, int width, int height, bool force) 
        {
            string suffix = width + "x" + height;
            string ofile;
            string thumb = ofile = filePath;
            string ext = thumb.Substring(thumb.LastIndexOf(".") + 1);
            string part1 = thumb.Substring(0, thumb.LastIndexOf("."));
            if (part1.IndexOf(".") == -1)
            {
                thumb = part1 + "." + suffix + "." + ext;
            }
            else
            {
                string part2 = part1.Substring(0, part1.LastIndexOf("."));
                thumb = part2 + "." + suffix + "." + ext;
            }
            
            var fileExist = File.Exists(AppDomain.CurrentDomain.BaseDirectory + thumb);
#if AZURE
            if (!fileExist)
            {
                fileExist = AzureBlob.DoesBlobItemExists(blobImageContainerName, thumb); 
            }
#endif
            if (!fileExist)
            {
                thumb = thumbnail(ofile, suffix, width, height);
            }
#if AZURE
            return AzureBlob.GetBlobItemUri(Img.blobImageContainerName, thumb);
#else
            return thumb;
#endif
        }

        static public string thumbnail(string filePath, string suffix, float desiredWidth, float desiredHeight) 
        {
            string thumb = filePath;
            string file = filePath;
            string ext = thumb.Substring(thumb.LastIndexOf(".") + 1);
            thumb = thumb.Substring(0, thumb.IndexOf(".")) + "." + suffix + "." + ext;
            // test to see if there are two suffixes in the same file name like 96x96.64x64
            // if there are then simply remove the first one and leave the second one
            // matches [set of chars].[set of chars].[set of chars].jpg
            Regex pattern = new Regex(@"/.*\..*\..*\.jpg/");
            if (pattern.Match(thumb).Success) 
            {
                string part1 = filePath.Substring(0, filePath.IndexOf("."));
                thumb = part1 + "." + desiredWidth + "x" + desiredWidth + ".jpg";
            }

            bool exists = File.Exists(AppDomain.CurrentDomain.BaseDirectory + file);

#if AZURE
            file = file.Substring(file.LastIndexOf("/") + 1);
            thumb = thumb.Substring(thumb.LastIndexOf("/") + 1);
            if (!exists)
            {
                exists = AzureBlob.DoesBlobItemExists(Img.blobImageContainerName, file);
            }
#endif
            if (!exists) 
            {
                return "";
            }
            // These are the ratio calculations
#if AZURE
            Image img = Image.FromStream(AzureBlob.GetBlobContent(Img.blobImageContainerName, file).AsStream);
#else
            Image img = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + file);
#endif
            int width = img.Width;
            int height = img.Height;
            float factor = 0;
            if (width > 0 && height > 0) 
            {
                float wfactor = desiredWidth / width;
                float hfactor = desiredHeight / height;
                factor = wfactor < hfactor ? wfactor : hfactor;
            }
            if (factor != 0 && factor < 1) 
            {
                int twidth = Convert.ToInt32(Math.Floor(factor * width));
                int theight = Convert.ToInt32(Math.Floor(factor * height));
                convert(file, thumb, twidth, theight);
            } 
            else 
            {
#if AZURE
                if (AzureBlob.DoesBlobItemExists(Img.blobImageContainerName, thumb))
                {
                    AzureBlob.DeleteBlobItem(Img.blobImageContainerName, thumb);
                }
                AzureBlob.CopyContent(Img.blobImageContainerName, file, thumb);
#else
                if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + thumb))
                {
                    File.Delete(AppDomain.CurrentDomain.BaseDirectory + thumb);
                }
                File.Copy(AppDomain.CurrentDomain.BaseDirectory + file, AppDomain.CurrentDomain.BaseDirectory + thumb);
#endif
            }
            return thumb;
        }

        static public void convert(string source, string destination, int desiredWidth, int desiredHeight) 
        {
            createImage(source, destination, desiredWidth, desiredHeight);
        }

        private static bool createImage(string srcName, string destName, int desiredWidth, int desiredHeight) 
        {
            var source = AppDomain.CurrentDomain.BaseDirectory + srcName;
            var destination = AppDomain.CurrentDomain.BaseDirectory + destName;
            // Capture the original size of the uploaded image
            Image src;
            try
            {
#if AZURE
                src = Image.FromStream(AzureBlob.GetBlobContent(Img.blobImageContainerName, srcName).AsStream);
#else
                src = Image.FromFile(source);
#endif
            }
            catch
            {
                return false;
            }
            //Resize new image
            Image tmp = src.GetThumbnailImage(desiredWidth, desiredHeight, null, IntPtr.Zero);
            
            try
            {
#if AZURE
                var container = AzureBlob.GetBlobContainer(Img.blobImageContainerName);
                var ms = new MemoryStream();
                tmp.Save(ms, ImageFormat.Jpeg);
                ms.Position = 0;
                var contents = new BlobContents(ms);
                var props = new BlobProperties(destName)
                            {
                                ContentType = "image/jpeg",
                            };
                AzureBlob.AddBlobItem(container, props, contents, true);
#else
                File.Delete(destination);
                tmp.Save(destination);
#endif
            }
            catch
            {
                return false;
            }
            finally
            {
                src.Dispose();
                tmp.Dispose();
            }
           
            return true;
        }

        static public bool saveImage(HttpPostedFileBase file, string destName)
        {
            try
            {
#if AZURE
                AzureBlob.DeleteBlobItem(Img.blobImageContainerName, destName);
                var destination = destName;
#else
                var destination = AppDomain.CurrentDomain.BaseDirectory + destName;
                // delete if exists
                if (File.Exists(destination))
                {
                    File.Delete(destination);
                }
#endif
                long filesize = file.ContentLength;
                using (Image objImage = Image.FromStream(file.InputStream))
                {
                    if (filesize > 640000 || objImage.Width > 640 || objImage.Height > 800)
                    {
                        int thumbHeight;
                        int thumbWidth;
                        if (objImage.Width >= objImage.Height)
                        {
                            thumbWidth = 640;
                            thumbHeight = objImage.Height * thumbWidth / objImage.Width;
                        }
                        else
                        {
                            thumbHeight = 800;
                            thumbWidth = objImage.Width * thumbHeight / objImage.Height;
                        }

                        // resize image
                        by_size(destination, thumbWidth, thumbHeight);
                    }
                    else
                    {
#if AZURE
                        var container = AzureBlob.CreateBlobContainer(Img.blobImageContainerName);
                        string blobname = Path.GetFileName(destination);
                        var blobproperties = new BlobProperties(blobname)
                                                 {
                                                     ContentType = file.ContentType
                                                 };
                        file.InputStream.Position = 0;
                        var blobcontents = new BlobContents(file.InputStream);
                        bool ok = AzureBlob.AddBlobItem(container, blobproperties, blobcontents, true);
#else
                        file.SaveAs(destination);
#endif

                    }
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
    }
}
